//bange_image.cpp
//Copyright (C) 2010-2011 Oscar (.teri) Triano

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <bange_image.hpp>

void bange::image::RegisterVM(lua_State *vm){
	luaL_Reg method[] = {
	{"SaveToFile", bangeimage_SaveToFile},
	{"CreateMaskFromColor", bangeimage_CreateMaskFromColor},
	//{"Copy", bangeimage_Copy},
	{"GetPixel", bangeimage_GetPixel},
	{"SetPixel", bangeimage_SetPixel},
	{NULL, NULL}};
	luaL_Reg function[] = {
	{"LoadImage", bangeimage_LoadImage},
	{NULL, NULL}};
	luaL_register(vm, NULL, function);
	luaL_newmetatable(vm, "bange::image_method");
	luaL_register(vm, NULL, method);
	lua_pop(vm, 1);
}

bool bange::image::NewIndex(lua_State *vm){
	//image, key, data
	char key[64] = {0};
	strncpy(key, lua_tostring(vm, 2), 64);
	if (strcmp("smooth", key) == 0 && lua_isboolean(vm, 3)){
		this->SetSmooth(static_cast<bool>(lua_toboolean(vm, 3)));
		return true;}
	return false;
}

bool bange::image::Index(lua_State *vm){
	//image, key
	char key[64] = {0};
	strncpy(key, lua_tostring(vm, 2), 64);
	if (strcmp("smooth", key) == 0){
		lua_pushboolean(vm, static_cast<int>(this->IsSmooth()));
		return true;}
	if (strcmp("bind", key) == 0){
		//Well, in this case the index perfoms like a method
		this->Bind();
		return true;}
	if (strcmp("width", key) == 0){
		lua_pushnumber(vm, static_cast<lua_Number>(this->GetWidth()));
		return true;}
	if (strcmp("height", key) == 0){
		lua_pushnumber(vm, static_cast<lua_Number>(this->GetHeight()));
		return true;}
	lua_getfield(vm, LUA_REGISTRYINDEX, "bange::image_method");
	lua_getfield(vm, -1, key);
	if(lua_isfunction(vm, -1)){
		return true;}
	lua_pop(vm, 2);//nil value, metatable
	return false;
}

static int bangeimage_LoadImage(lua_State *vm){
	//filename(string)
	//Remember: We are loading from a package
	if(!lua_isstring(vm, 1)){
		cout << "bange.LoadImage: First argument isn't a string" << endl;
		lua_pushnil(vm);
		return 1;}
	bange::image *image;
	char *stringimage = NULL;
	PHYSFS_sint64 readed = bange::readbinaryfrompackage(lua_tostring(vm, 1), &stringimage);
	if (readed < 1){
		cout << "bange.LoadImage: Isn't possibble load the image " << lua_tostring(vm, 1) << "." << endl;
		delete stringimage;
		lua_pushnil(vm);
		return 1;}
	image = new bange::image;
	image->LoadFromMemory(stringimage, static_cast<std::size_t>(readed));
	bange::BuildProxy(LUA_REFNIL, static_cast<bange::base *>(image), vm);
	return 1;
}

static int bangeimage_SaveToFile(lua_State *vm){
    //image, file -> boolean
    if (lua_isnumber(vm, 2) || !lua_isstring(vm, 2)){
        lua_pushboolean(vm, 0);
        return 1;}
    bange::image *image = static_cast<bange::image *>(bange::base::GetBaseFromProxy(1, vm));
    int b = image->SaveToFile(lua_tostring(vm, 2));
    lua_pushboolean(vm, b);
    return 1;
}

static int bangeimage_CreateMaskFromColor(lua_State *vm){
    //userdata, {r, g, b, (a)}, alpha
    sf::Color color(0, 0, 0);
    sf::Uint8 alpha = 0;
    if (!lua_istable(vm, 2)){
        return 0;}
    bange::aux::ComposeColor(2, color, vm);
    color.a = 255;
    if (lua_isnumber(vm, 3)){
        alpha = static_cast<sf::Uint8>(lua_tonumber(vm, 3));}
    bange::image *image = static_cast<bange::image *>(bange::base::GetBaseFromProxy(1, vm));
    image->CreateMaskFromColor(color, alpha);
    return 0;
}

/*
static int bangeimage_Copy(lua_State *vm){
    //bange::image, bange::image, DestX, DestY, {Left, Top, Right, Bottom}
    if (lua_type(vm, 2) != LUA_TUSERDATA){
        printf("\nFirst argument must be a userdata");
        return 0;}
    lua_getmetatable(vm, 2);
    lua_pushstring(vm, "bange_image");
    lua_gettable(vm, LUA_REGISTRYINDEX);
    if (!lua_equal(vm, -1, -2)){
        printf("\nSecond argument must be a bange_image");
        return 0;}
    lua_pop(vm, 2);
    if (!lua_isnumber(vm, 3)){
        printf("\nThird argument must be a number");
        return 0;}
    if (!lua_isnumber(vm, 4)){
        printf("\nFourth argument must be a number");
        return 0;}
    sf::Image *firstimage = static_cast<sf::Image *>(lua_touserdata(vm, 1));
    sf::Image *secondimage = static_cast<sf::Image *>(lua_touserdata(vm, 2));
    sf::IntRect source(0, 0, 0, 0);
    source.Right = secondimage->GetWidth();
    source.Bottom = secondimage->GetHeight();
    if (lua_istable(vm, 5)){
        lua_pushnumber(vm, 1);
        lua_gettable(vm, 5);
        if (lua_isnumber(vm, -1)){
            source.Left = static_cast<int>(lua_tonumber(vm, -1));}
        lua_pop(vm, 1);
        lua_pushnumber(vm, 2);
        lua_gettable(vm, 5);
        if (lua_isnumber(vm, -1)){
            source.Top = static_cast<int>(lua_tonumber(vm, -1));}
        lua_pop(vm, 1);
        lua_pushnumber(vm, 3);
        lua_gettable(vm, 5);
        if (lua_isnumber(vm, -1)){
            source.Right = static_cast<int>(lua_tonumber(vm, -1));}
        lua_pop(vm, 1);
        lua_pushnumber(vm, 4);
        lua_gettable(vm, 5);
        if (lua_isnumber(vm, -1)){
            source.Bottom = static_cast<int>(lua_tonumber(vm, -1));}
        lua_pop(vm, 1);
    }
    firstimage->Copy(*secondimage, \
    static_cast<unsigned int>(lua_tonumber(vm, 3)), \
    static_cast<unsigned int>(lua_tonumber(vm, 4)), source);
    return 0;
}
*/

static int bangeimage_SetPixel(lua_State *vm){
	//userdata, x, y, {r, g, b, a}
	if (!lua_isnumber(vm, 2) || !lua_isnumber(vm, 3)){
		lua_pushnil(vm);
		return 1;}
	unsigned int x, y;
	x = static_cast<unsigned int>(lua_tonumber(vm, 2));
	y = static_cast<unsigned int>(lua_tonumber(vm, 3));
	sf::Color color(0, 0, 0);
	bange::aux::ComposeColor(4, color, vm);
	bange::image *image = static_cast<bange::image *>(bange::base::GetBaseFromProxy(1, vm));
	image->SetPixel(x, y, color);
	return 0;
}

static int bangeimage_GetPixel(lua_State *vm){
	//userdata, x, y
	if (!lua_isnumber(vm, 2) || !lua_isnumber(vm, 3)){
		lua_pushnil(vm);
		return 1;}
	unsigned int x, y;
	x = static_cast<unsigned int>(lua_tonumber(vm, 2));
	y = static_cast<unsigned int>(lua_tonumber(vm, 3));
	bange::image *image = static_cast<bange::image *>(bange::base::GetBaseFromProxy(1, vm));
	sf::Color color(0, 0, 0);
	color = image->GetPixel(x, y);
	bange::aux::ComposeTupleFromColor(color, vm);//+1, -0
	return 1;
}
